package com.atwisdom.star.core.bsl.customized.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.function.AtwisdomMapFunction;
import com.atwisdom.star.common.util.DateUtils;
import com.atwisdom.star.common.util.ExpressionUtil;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.vo.ModelType;
import com.atwisdom.star.common.vo.StatusCode;
import com.atwisdom.star.core.bsl.customized.SalaryBslService;
import com.atwisdom.star.core.bsl.modelClass.logic.LogicInstanceBslService;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dsl.functionClass.BatchNumberDslService;
import com.atwisdom.star.core.dsl.modelClass.consume.ConsumeInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.staticLogic.StaticLogicInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.twins.TwinsInstanceDslService;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.googlecode.aviator.AviatorEvaluator;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 薪资服务，提供薪资计算相关的方法
 * @Date: 2023-11-08 10:00
 */
@Slf4j
@AllArgsConstructor
@Service
public class SalaryBslServiceImpl implements SalaryBslService {

    private LogicInstanceDslServiceImpl logicInstanceDslService;
    private ResourceInstanceDslServiceImpl resourceInstanceDslService;
    private StaticLogicInstanceDslService staticLogicInstanceDslService;
    private ConsumeInstanceDslService consumeInstanceDslService;
    private TwinsInstanceDslService twinsInstanceDslService;
    private HierInstanceDslService hierInstanceDslService;
    private BatchNumberDslService batchNumberDslService;
    private LogicInstanceBslService logicInstanceBslService;
    // private AutoGenUtil autoGenUtil;


    /**
     * 查询所有的员工
     */
    public List<JSONObject> queryAllStaff(String endTime) {
        String className = "person";
        String condition = " entryTime <= '" + endTime + "'";

        //  todo:  id in( 130, 237)  130 职员， 237班长   测试数据，上线前删除
        // condition += " and id in( 1629)";
        List<JSONObject> staffList = resourceInstanceDslService.query(condition, className, null);
        List<JSONObject> availableList = staffList.stream().filter(d -> d.getJSONObject("values").get("salaryCategory_level") != null).collect(Collectors.toList());
        return availableList;
    }

    /**
     * 查询所有的员工
     */
    public List<JSONObject> queryAllStaff() {
        String className = "person";
        // String condition = " entryTime >= '" + beginTime + "' and entryTime <= '" + endTime + "'";
        //  todo:  id in( 130, 237)  130 职员， 237班长   测试数据，上线前删除
        String condition = "";
        // condition += " and id in( 130, 237, 244)";
        List<JSONObject> staffList = resourceInstanceDslService.query(condition, className, null);
        return staffList;
    }

    /**
     * 查询会计期
     */
    public JSONObject queryAccountPeriod(Integer fiscalYear, Integer fiscalMonth) {
        String className = "AccountPeriod";
        String condition = "fiscalYear = " + fiscalYear + " and fiscalMonth = " + fiscalMonth;
        List<JSONObject> accountPeriodList = logicInstanceDslService.query(condition, className, null);
        if (CollectionUtil.isNotEmpty(accountPeriodList)) {
            return accountPeriodList.get(0);
        }
        return null;
    }

    private void throwException(String msg) {
        throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), msg);
    }

    /**
     * 1. 查询所有员工
     * 2. 获取员工的薪资类别id， salaryCategory_id
     * 3. 获取会计期 AccountPeriod，获取所有员工报工数量
     * 4. 获取薪资类别对应的公式
     * 4. 解析公式
     * @return
     */
    @Override
    public Map<String, Object> calculateSalary(JSONObject dataJson) throws IllegalAccessException, NoSuchMethodException {
        // AviatorEvaluator.addStaticFunctions("atwisdomMapFunction", AtwisdomMapFunction.class);
        AviatorEvaluator.addStaticFunctions("mapFun", AtwisdomMapFunction.class);
        Long containerId = dataJson.getLong("containerId");
        JSONObject salaryContainer = logicInstanceDslService.queryJsonById(containerId);
        String yearMonth = salaryContainer.getJSONObject("values").getString("yearMonth");
        String[] yearMonthSplit = yearMonth.split("-");
        Integer fiscalYear = Integer.valueOf(yearMonthSplit[0]);
        Integer fiscalMonth = Integer.valueOf(yearMonthSplit[1]);

        // 查询会计期
        JSONObject accountPeriod = queryAccountPeriod(fiscalYear, fiscalMonth);
        if (accountPeriod == null) {
            throwException("会计期不存在");
        }

        String beginTime = accountPeriod.getJSONObject("values").getString("beginTime");
        String endTime = accountPeriod.getJSONObject("values").getString("endTime");

        // 查询会计期内入职的员工
        List<JSONObject> staffList = queryAllStaff(endTime);
        Map<String, JSONObject> staffCodeMap = staffList.stream().collect(Collectors.toMap(d -> d.getJSONObject("values").getString("code"),
                d -> d.getJSONObject("values")));

        // 查询报工单
        // "#", teamId, staffId, lineBody, materialBcode : quantity
        Map<String, Integer> workReportDetailMap = queryWorkReport(beginTime, endTime);
        if (CollectionUtil.isEmpty(workReportDetailMap)) {
            log.info("报工数据为空");
        }

        // 班组报工数量
        Map<String, Integer> teamWorkReportDetailMap = new HashMap<>();
        workReportDetailMap.forEach((k,v) -> {
            String teamKeyPrefix = k.substring(0, k.indexOf('#'));
            int secondIndex = k.indexOf('#', k.indexOf('#') + 1);
            String teamKeySuffix = k.substring(secondIndex);
            // teamId#lineBody#materialBcode  每个班组报工数
            String teamKey = teamKeyPrefix + teamKeySuffix;
            teamWorkReportDetailMap.merge(teamKey, v, Integer::sum);
            // if (teamWorkReportDetailMap.containsKey(teamKey)) {
            //     // AviatorEvaluator.execute(v), String::join
            //     teamWorkReportDetailMap.put(teamKey, v);
            // } else {
            //     teamWorkReportDetailMap.put(teamKey, v);
            // }
        });

        // 查询工序价格表中单次操作次数和价格  "#", lineBody, materialBcode
        Map<String, String>  materialProcessPriceMap = queryAllMaterialProcessPrice();

        // 将价格与报工单中的数据一一对应，便于后面计算
        Map<String, String> workReportDetailPriceMap = new HashMap<>();
        workReportDetailMap.forEach((k,v) -> {
            int secondIndex = k.indexOf('#', k.indexOf('#') + 1);
            String priceKey = k.substring(secondIndex + 1);
            String priceExpression = materialProcessPriceMap.getOrDefault(priceKey, "0");
            workReportDetailPriceMap.put(k, priceExpression);
        });

        // 将价格与班组报工单中的数据一一对应，便于后面计算 teamId#lineBody#materialBcode : priceExpression  每个班组报工数对应的单价*工序数量
        Map<String, String> teamWorkReportDetailPriceMap = new HashMap<>();
        teamWorkReportDetailMap.forEach((k,v) -> {
            String priceKey = k.substring(k.indexOf('#') + 1);
            String priceExpression = materialProcessPriceMap.getOrDefault(priceKey, "0");
            teamWorkReportDetailPriceMap.put(k, priceExpression);
        });

        // 查询所有的工资计算公式
        Map<Long, JSONObject>  salaryCategoryMap = queryAllSalaryCategory();

        // 组装公式计算用到的参数
        // 组装参数
        Map<String,Object> calculateParamMap = new HashMap();
        // 个人报工数量
        calculateParamMap.put("workReport", workReportDetailMap);
        // 班组报工数量
        calculateParamMap.put("teamWorkReport", teamWorkReportDetailMap);
        // 背番需要工序的次数和价格
        calculateParamMap.put("workReportDetailPrice", workReportDetailPriceMap);
        // 班组背番需要工序的次数和价格
        calculateParamMap.put("teamWorkReportDetailPrice", teamWorkReportDetailPriceMap);

        // 查询计时员工基本工资与绩效工资
        Map<String, JSONObject> hourlySalaryMap = queryHourlySalary();
        Map<String, Double> hourlyBasicSalaryMap = new HashMap<>();
        Map<String, Double> hourlyPerformanceSalaryMap = new HashMap<>();
        hourlySalaryMap.forEach((k, v) -> {
            hourlyBasicSalaryMap.put(k, v.getJSONObject("values").getDouble("basic"));
            hourlyPerformanceSalaryMap.put(k, v.getJSONObject("values").getDouble("performance"));
        });
        calculateParamMap.put("hourlyBasic", hourlyBasicSalaryMap);
        calculateParamMap.put("hourlyPerformance", hourlyPerformanceSalaryMap);


        // 查询系统标准工时
        Integer systemStandardManHour = querySystemStandardManHour();
        calculateParamMap.put("systemStandardManHour", systemStandardManHour);

        // 查询员工标准工时，
        Map<String, Double> standardManHourMap = queryStandardManHour(salaryCategoryMap);
        calculateParamMap.put("standardManHour", standardManHourMap);

        // 以teamId + "#" + staffId为key
        // Map<String, Object> actualManHourMap = queryActualManHour(fiscalYear, fiscalMonth, staffList, standardManHourMap);
        // calculateParamMap.put("actualManHour", actualManHourMap);

        // 查询考勤表， 以person_code为key
        Map<String, JSONObject> workAttendanceMap = queryWorkAttendance(fiscalYear + "-" + fiscalMonth);
        calculateParamMap.put("workAttendance", workAttendanceMap);
        Map<String, String> staffCodeTeamMap = staffList.stream().collect(Collectors.toMap(d -> d.getJSONObject("values").getString("code"),
                d -> d.getJSONObject("values").getString("team_id") != null ? d.getJSONObject("values").getString("team_id") : ""));
        // 计算班组总出勤时长
        Map<String, Double> teamWorkHourMap = queryTeamWorkHour(workAttendanceMap, staffCodeTeamMap);
        calculateParamMap.put("teamWorkHour", teamWorkHourMap);

        // 查询夜班天数与绩效金额
        Map<String, BigDecimal> driverPerformanceMap = queryDriverPerformance(fiscalYear + "-" + fiscalMonth);
        Map<String, Integer> driverNightShiftMap = queryDriverNightShift(fiscalYear + "-" + fiscalMonth);
        calculateParamMap.put("driverBaseSalary", driverPerformanceMap);
        calculateParamMap.put("driverNightShift", driverNightShiftMap);


        // 查询派工完结单
        String dispatchBeginTime = DateUtils.getStartOfMonth(fiscalYear, fiscalMonth);
        String dispatchEndTime = DateUtils.getEndOfMonth(fiscalYear, fiscalMonth);
        Map<String, Double> dispatchCompleteMap = queryDispatchComplete(dispatchBeginTime, dispatchEndTime);
        calculateParamMap.put("dispatchComplete", dispatchCompleteMap);

        // 查询入职时间 entryTime
        Map<Long, Long> workAgeMap = staffList.stream().collect(Collectors.toMap(d -> d.getLong("id"), d -> {
            Date entryTime = d.getJSONObject("values").getDate("entryTime");
            return DateUtil.betweenYear(entryTime, DateUtil.parseDate(fiscalYear + "-" + fiscalMonth+ "-01"), false);
        }));
        calculateParamMap.put("workAge", workAgeMap);

        //查询保险
        Map<String, Object> insuranceMap = queryInsurance(fiscalYear + "-" + fiscalMonth);
        calculateParamMap.put("insurance", insuranceMap);

        //查询个税
        Map<String, Object> personTaxMap = queryPersonTax(fiscalYear + "-" + fiscalMonth);
        calculateParamMap.put("personTax", personTaxMap);

        // 过滤出基层员工，即工资只算工作，不会使用他人数据的员工
        List<JSONObject> firstLevelStaffList = staffList.stream().filter(d ->  {
            Integer salaryCategoryLevel = d.getJSONObject("values").getInteger("salaryCategory_level");
            return salaryCategoryLevel == null || salaryCategoryLevel == 1;
        }).collect(Collectors.toList());
        // 过滤出非基层员工  （本班组计件金额总和）/本班组工时总和*个人出勤时长*固定系数
        List<JSONObject> otherLevelStaffList = staffList.stream().filter(d -> {
            Integer salaryCategoryLevel = d.getJSONObject("values").getInteger("salaryCategory_level");
            return salaryCategoryLevel != null && salaryCategoryLevel != 1;
        }).collect(Collectors.toList());

        // 计算最基层员工的薪资， 并设置calculateParamMap参数"firstLevelSalary"
        calculateFirstLevelSalary(salaryCategoryMap, calculateParamMap, firstLevelStaffList);

        // 计算第二层员工薪资
        calculateSecondLevelSalary(salaryCategoryMap, calculateParamMap, otherLevelStaffList);

        // calculateAllStaffSalary(salaryCategoryMap, calculateParamMap, staffList);

        log.info("calculateParamMap = {}", JSONObject.toJSON(calculateParamMap));

        // 将数值写入薪资表
        hierInstanceDslService.deleteByContainerId("logic", containerId);
        List<JSONObject> firstSalaryList = buildSalaryTable(calculateParamMap, firstLevelStaffList, "firstLevelSalary");
        List<JSONObject> otherSalaryList = buildSalaryTable(calculateParamMap, otherLevelStaffList, "secondLevelSalary");
        hierInstanceDslService.addChild(ModelType.Logic.getCode(), "salaryTable", containerId, "4d0o0x8q2dm000", firstSalaryList);
        hierInstanceDslService.addChild(ModelType.Logic.getCode(), "salaryTable", containerId, "4d0o0x8q2dm000", otherSalaryList);
        return calculateParamMap;
    }


    /**
     * 查询计算员工工资
     * @return
     */
    private Map<String, JSONObject> queryHourlySalary() {
        String className = "hourlyWage";
        List<JSONObject> list = resourceInstanceDslService.query(null, className, null);
        Map<String, JSONObject> codeSalaryMap = list.stream().collect(Collectors.toMap(d -> d.getJSONObject("values").getString("person_code"), d -> d, (k1, k2) -> k1));
        return codeSalaryMap;
    }

    /**
     * 查询司机绩效
     * @param yearAndMonth
     * @return
     */
    private Map<String, BigDecimal> queryDriverPerformance(String yearAndMonth) {
        // 司机绩效工资
        Map<String, BigDecimal>  driverSalaryMap= new HashMap<>();
        Map<String, BigDecimal> truckSendPriceMap = queryTruckSendPrice();
        String className = "driverPerformance";
        String condition = " isApproved = 1 and yearMonth = " + yearAndMonth;
        List<JSONObject> list = logicInstanceDslService.queryWithoutHier(condition, className, "");
        if (CollectionUtil.isNotEmpty(list)) {
            List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId("logic", list.get(0).getLong("id"), className, "parentId = 'root'");
            // 0830001
            // 根据send_code查询价格  person_code salaryMultiple isNightShift
            hierInstanceList.forEach(hierInstance -> {
                JSONObject hierValues = hierInstance.getValues();
                String personCode = hierValues.getString("person_code");
                BigDecimal price = truckSendPriceMap.getOrDefault(personCode, BigDecimal.ZERO);
                BigDecimal salaryMultiple = hierValues.getBigDecimal("salaryMultiple");
                BigDecimal amount = price.multiply(salaryMultiple).setScale(2, RoundingMode.HALF_UP);
                driverSalaryMap.merge(personCode, amount, BigDecimal::add);
            });
        }
        return driverSalaryMap;
    }

    /**
     * 查询五险一金
     * @param yearAndMonth
     * @return
     */
    private Map<String, Object> queryInsurance(String yearAndMonth) {
        // 司机绩效工资
        Map<String, Object> resultMap= new HashMap<>();
        String className = "salaryImportInsure";
        String condition = " isApproved = 1 and yearMonth = '" + yearAndMonth +"'";
        List<JSONObject> list = logicInstanceDslService.queryWithoutHier(condition, className, "");
        if (CollectionUtil.isNotEmpty(list)) {
            List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId("logic", list.get(0).getLong("id"), className, "parentId = 'root'");
            hierInstanceList.forEach(hierInstance -> {
                JSONObject hierValues = hierInstance.getValues();
                String personCode = hierValues.getString("person_code");
                resultMap.put(personCode, hierValues);
            });
        }
        return resultMap;
    }

    /**
     * 查询个税代扣
     * @param yearAndMonth
     * @return
     */
    private Map<String, Object> queryPersonTax(String yearAndMonth) {
        // 司机绩效工资
        Map<String, Object> resultMap= new HashMap<>();
        String className = "salaryImportPersonTax";
        String condition = " isApproved = 1 and yearMonth = " + yearAndMonth;
        List<JSONObject> list = logicInstanceDslService.queryWithoutHier(condition, className, "");
        if (CollectionUtil.isNotEmpty(list)) {
            List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId("logic", list.get(0).getLong("id"), className, "parentId = 'root'");
            hierInstanceList.forEach(hierInstance -> {
                JSONObject hierValues = hierInstance.getValues();
                String personCode = hierValues.getString("person_code");
                resultMap.put(personCode, hierValues.getBigDecimal("personTax"));
            });
        }
        return resultMap;
    }

    /**
     * 查询司机夜班
     * @param yearAndMonth
     * @return
     */
    private Map<String, Integer> queryDriverNightShift(String yearAndMonth) {
        // 司机夜班趟数
        Map<String, Integer>  driverNightMap= new HashMap<>();
        String className = "driverPerformance";
        String condition = " isApproved = 1 and yearMonth = " + yearAndMonth;
        List<JSONObject> list = logicInstanceDslService.queryWithoutHier(condition, className, "");
        if (CollectionUtil.isNotEmpty(list)) {
            List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId("logic", list.get(0).getLong("id"), className, "parentId = 'root'");
            // 0830001
            // 根据send_code查询价格  person_code salaryMultiple isNightShift
            hierInstanceList.forEach(hierInstance -> {
                JSONObject hierValues = hierInstance.getValues();
                String personCode = hierValues.getString("person_code");
                // 是否夜班
                Boolean isNightShift = hierValues.getBoolean("isNightShift");
                if (isNightShift) {
                    driverNightMap.merge(personCode, 1, Integer::sum);
                }
            });
        }
        return driverNightMap;
    }

    /**
     * 查询送货价格  truckSendPrice  sendPrice
     * @return
     */
    private Map<String, BigDecimal> queryTruckSendPrice() {
        Map<String, BigDecimal> truckSendPriceMap = new HashMap<>();
        String className = "truckSendPrice";
        String condition = " isApproved = 1";
        List<JSONObject> list = resourceInstanceDslService.query(condition, className, "");
        if (CollectionUtil.isNotEmpty(list)) {
            truckSendPriceMap = list.stream().collect(Collectors.toMap(d -> d.getJSONObject("values").getString("code"), d -> d.getJSONObject("values").getBigDecimal("sendPrice")));
        }
        return truckSendPriceMap;
    }

    /**
     * 计算班组总出勤时长
     * @param workAttendanceMap
     * @param staffCodeTeamMap
     */
    private Map<String, Double> queryTeamWorkHour(Map<String, JSONObject> workAttendanceMap, Map<String, String> staffCodeTeamMap) {
        Map<String, Double> teamWorkAttendanceHour = new HashMap<>();
        staffCodeTeamMap.forEach((personCode, teamId) -> {
            JSONObject workAttendance = workAttendanceMap.get(personCode);
            if (workAttendance != null) {
                Double workAttendanceHour = workAttendance.getDouble("workAttendanceHour");
                workAttendanceHour = workAttendanceHour != null ? workAttendanceHour : 0D;
                teamWorkAttendanceHour.merge(teamId, workAttendanceHour, Double::sum);
            } else {
                if (!teamWorkAttendanceHour.containsKey(teamId)) {
                    teamWorkAttendanceHour.put(teamId, 0.0);
                }
            }
        });
        return teamWorkAttendanceHour;
    }

    /**
     * 构建薪资表所需数据
     * @param calculateParamMap
     * @param staffList
     */
    private List<JSONObject> buildSalaryTable(Map<String, Object> calculateParamMap, List<JSONObject> staffList, String salaryLevelKey) {
        List<JSONObject> resultList = new ArrayList<>();
        // 查询所有班组 和 部门
        Map<String, JSONObject> teamMap = queryAllTeam();
        Map<String, JSONObject> deptMap = queryAllDept();
        JSONObject levelSalaryJson = JsonUtil.toJSONObject(calculateParamMap.get(salaryLevelKey));
        JSONObject allWorkAttendanceJson = JsonUtil.toJSONObject(calculateParamMap.get("workAttendance"));
        JSONObject allInsuranceJson = JsonUtil.toJSONObject(calculateParamMap.get("insurance"));
        JSONObject allPersonTaxJson = JsonUtil.toJSONObject(calculateParamMap.get("personTax"));
        staffList.forEach(staff->{
            Long staffId = staff.getLong("id");
            JSONObject staffValue = staff.getJSONObject("values");
            String personCode = staffValue.getString("code");
            String personName = staffValue.getString("name");
            String phone = staffValue.getString("phone");
            String teamId = staffValue.getString("team_id");
            String deptId = staffValue.getString("dept_id");
            String deptName = deptMap.get(deptId).getString("name");
            JSONObject workAttendanceJson = allWorkAttendanceJson.getJSONObject(personCode);
            JSONObject insuranceJson = allInsuranceJson.getJSONObject(personCode);

            String staffKey = StrUtil.join("#", teamId, staffId);
            JSONObject salaryJson = levelSalaryJson.getJSONObject(staffKey);
            // 基本工资
            BigDecimal baseSalary = getBigDecimalOrDefaultZero(salaryJson, "baseSalary");
            // 绩效工资
            BigDecimal performancePay = getBigDecimalOrDefaultZero(salaryJson, "performance");
            // 防暑降温
            BigDecimal sunstrokePrevention = getBigDecimalOrDefaultZero(salaryJson, "sunstrokePrevention");
            // 取暖补贴
            BigDecimal heatingSubsidy = getBigDecimalOrDefaultZero(salaryJson, "heatingSubsidy");
            // 其他奖励/补贴
            BigDecimal otherSubsidy = getBigDecimalOrDefaultZero(salaryJson, "otherSubsidy");
            // 夜班补助
            BigDecimal nightSubsidy = getBigDecimalOrDefaultZero(salaryJson, "nightSubsidy");
            // 交通补贴
            BigDecimal trafficSubsidy = getBigDecimalOrDefaultZero(salaryJson, "trafficSubsidy");
            // 工龄奖
            BigDecimal workingSubsidy = getBigDecimalOrDefaultZero(salaryJson, "workingSubsidy");
            // 岗位津贴
            BigDecimal jobSubsidy = getBigDecimalOrDefaultZero(salaryJson, "jobSubsidy");
            // 病假扣除
            BigDecimal sickDeduction = getBigDecimalOrDefaultZero(salaryJson, "sickDeduction");
            // 事假扣除
            BigDecimal personalDeduction = getBigDecimalOrDefaultZero(salaryJson, "personalDeduction");
            // 其他扣除
            BigDecimal otherDeduction = getBigDecimalOrDefaultZero(salaryJson, "otherDeduction");
            // 全勤奖金
            BigDecimal fullAttendance = getBigDecimalOrDefaultZero(salaryJson, "fullAttendance");

            // 平日加班时长与薪资
            BigDecimal dailyOverTimeHour = getBigDecimalOrDefaultZero(workAttendanceJson, "dailyOverTimeHour");
            BigDecimal dailyOverTime = getBigDecimalOrDefaultZero(salaryJson, "dailyOverTime");
            // 休日加班时长与薪资
            BigDecimal weekendOverTimeHour = getBigDecimalOrDefaultZero(workAttendanceJson, "weekendOverTimeHour");
            BigDecimal weekendOverTime = getBigDecimalOrDefaultZero(salaryJson, "weekendOverTime");
            // 节日加班时长与薪资
            BigDecimal holidayOverTimeHour = getBigDecimalOrDefaultZero(workAttendanceJson, "holidayOverTimeHour");
            BigDecimal holidayOverTime = getBigDecimalOrDefaultZero(salaryJson, "holidayOverTime");
            // 病假
            BigDecimal sickLeaveHour = getBigDecimalOrDefaultZero(workAttendanceJson, "sickLeaveHour");
            // 事假
            // BigDecimal personalHour = getBigDecimalOrDefaultZero(workAttendanceJson, "personalHour");
            BigDecimal personalHour = getBigDecimalOrDefaultZero(workAttendanceJson, "dailyOffDutyHour");
            // 低级不良流出防止奖励
            BigDecimal defectiveOutflow = getBigDecimalOrDefaultZero(workAttendanceJson, "defectiveOutflow");
            // 不良扣除
            BigDecimal defectiveDeduction = getBigDecimalOrDefaultZero(workAttendanceJson, "defectiveDeduction");
            // 工会经费
            BigDecimal tradeUnion = getBigDecimalOrDefaultZero(workAttendanceJson, "tradeUnion");


            BigDecimal payableSalary = bigDecimalSum(baseSalary, performancePay, sunstrokePrevention,
                    heatingSubsidy, fullAttendance, otherSubsidy, nightSubsidy, trafficSubsidy, workingSubsidy, jobSubsidy,
                    dailyOverTime, weekendOverTime, holidayOverTime);

            // 税前工资
            payableSalary = bigDecimalSubtract(payableSalary, sickDeduction, personalDeduction, otherDeduction, defectiveOutflow,
                    defectiveDeduction, tradeUnion);

            // 五险一金
            BigDecimal workInjury = getBigDecimalOrDefaultZero(insuranceJson, "personWorkInjury");
            BigDecimal maternity = getBigDecimalOrDefaultZero(insuranceJson, "personMaternity");
            BigDecimal endowment = getBigDecimalOrDefaultZero(insuranceJson, "personEndowment");
            BigDecimal medical = getBigDecimalOrDefaultZero(insuranceJson, "personMedical");
            BigDecimal unemployment = getBigDecimalOrDefaultZero(insuranceJson, "personUnemployment");
            BigDecimal publicFunds = getBigDecimalOrDefaultZero(insuranceJson, "personPublicFunds");

            // 个税
            BigDecimal personTax = getBigDecimalOrDefaultZero(allPersonTaxJson, personCode);

            JSONObject salaryTableDataJson = new JSONObject();
            salaryTableDataJson.put("dept_name", deptName);
            salaryTableDataJson.put("person_code", personCode);
            salaryTableDataJson.put("person_name", personName);
            salaryTableDataJson.put("phone", phone);
            BigDecimal systemStandardManHour = new BigDecimal(String.valueOf(calculateParamMap.get("systemStandardManHour")));
            salaryTableDataJson.put("attendanceDays", getBigDecimalOrDefaultZero(workAttendanceJson, "workAttendanceHour").divide(systemStandardManHour).setScale(2, RoundingMode.HALF_UP));
            salaryTableDataJson.put("baseSalary", baseSalary);
            salaryTableDataJson.put("performancePay", performancePay);
            salaryTableDataJson.put("sunstrokePrevention", sunstrokePrevention);
            salaryTableDataJson.put("heatingSubsidy", heatingSubsidy);
            salaryTableDataJson.put("fullAttendance", fullAttendance);
            salaryTableDataJson.put("otherSubsidy", otherSubsidy);
            salaryTableDataJson.put("nightSubsidy", nightSubsidy);
            salaryTableDataJson.put("trafficSubsidy", trafficSubsidy);
            salaryTableDataJson.put("workingSubsidy", workingSubsidy);
            salaryTableDataJson.put("jobSubsidy", jobSubsidy);
            salaryTableDataJson.put("dailyOverTimeHour", dailyOverTimeHour);
            salaryTableDataJson.put("dailyOverTime", dailyOverTime);
            salaryTableDataJson.put("weekendOverTimeHour", weekendOverTimeHour);
            salaryTableDataJson.put("weekendOverTime", weekendOverTime);
            salaryTableDataJson.put("holidayOverTimeHour", holidayOverTimeHour);
            salaryTableDataJson.put("holidayOverTime", holidayOverTime);
            // salaryTableDataJson.put("sickLeave", sickLeave);
            salaryTableDataJson.put("sickHour", sickLeaveHour);
            salaryTableDataJson.put("sickDeduction", sickDeduction);
            salaryTableDataJson.put("personalHour", personalHour);
            salaryTableDataJson.put("personalDeduction", personalDeduction);
            salaryTableDataJson.put("otherDeduction", otherDeduction);
            salaryTableDataJson.put("defectiveOutflow", defectiveOutflow);
            salaryTableDataJson.put("defectiveDeduction", defectiveDeduction);
            salaryTableDataJson.put("tradeUnion", tradeUnion);
            salaryTableDataJson.put("payableSalary", payableSalary);
            salaryTableDataJson.put("workInjury", workInjury);
            salaryTableDataJson.put("maternity", maternity);
            salaryTableDataJson.put("endowment", endowment);
            salaryTableDataJson.put("medical", medical);
            salaryTableDataJson.put("unemployment", unemployment);
            // salaryTableDataJson.put("publicFunds", publicFunds);
            salaryTableDataJson.put("proFundStaff", publicFunds);
            salaryTableDataJson.put("personTax", personTax);
            // 实得工资
            BigDecimal netSalary = bigDecimalSubtract(payableSalary, workInjury, maternity, endowment,
                    medical, unemployment, publicFunds, personTax);
            salaryTableDataJson.put("netSalary", netSalary);

            JSONObject resultJson = new JSONObject();
            resultJson.put("hierValues", salaryTableDataJson);
            resultList.add(resultJson);
        });
        return resultList;
    }

    private BigDecimal bigDecimalSum(BigDecimal... numbers) {
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal num : numbers) {
            sum = sum.add(num);
        }
        return sum;
    }

    private BigDecimal bigDecimalSubtract(BigDecimal... numbers) {
        BigDecimal result = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            result = result.subtract(numbers[i]);
        }
        return result;
    }

    private BigDecimal getBigDecimalOrDefaultZero(JSONObject salaryJson, String key) {
        if (salaryJson == null || salaryJson.get(key) == null || StrUtil.isBlank(salaryJson.getString(key))) {
            return BigDecimal.ZERO;
        } else {
            return salaryJson.getBigDecimal(key);

        }
    }

    /**
     * 查询员工实际出勤时间， 以teamId + "#" + staffId为key
     * @param fiscalYear
     * @param fiscalMonth
     * @param staffList
     * @return
     */
    @Deprecated
    private Map<String, Object> queryActualManHour(Integer fiscalYear, Integer fiscalMonth, List<JSONObject> staffList, Map<Long, Double> standardManHourMap) {
        Map<String, Object> workAttendanceMap = new HashMap<>();
        Map<String, JSONObject> workAttendance = queryWorkAttendance(fiscalYear + "-" + fiscalMonth);
        staffList.stream().forEach(staff->{
            String personCode = staff.getJSONObject("values").getString("code");
            String teamId = staff.getJSONObject("values").getString("team_id");
            Long salaryCategoryId = Long.valueOf( staff.getJSONObject("values").getString("salaryCategory_id"));
            Long staffId = staff.getLong("id");
            Double standardManHour = standardManHourMap.get(salaryCategoryId);
            workAttendanceMap.put(teamId + "#" + staffId, standardManHour);
        });
        return workAttendanceMap;
    }

    /**
     * 计算第二层员工的薪资，并将计算结果存放到后续计算需要的参数{@code calculateParamMap}中
     * @param salaryCategoryMap
     * @param calculateParamMap
     * @param staffList
     * @return
     */
    private Map<String, Map<String, Object>> calculateAllStaffSalary(Map<Long, JSONObject> salaryCategoryMap, Map<String, Object> calculateParamMap, List<JSONObject> staffList) {
        // key = teamId#userId
        Map<String, Map<String, Object>> salaryMap = new HashMap<>();
        for (int i = 0; i < staffList.size(); i++) {
            Long staffId = staffList.get(i).getLong("id");
            JSONObject staffValues = staffList.get(i).getJSONObject("values");
            String teamId = staffValues.getString("team_id");
            String staffCode = staffValues.getString("code");
            // 存储一个班组下的员工
            HashMap<String, Object>  salaryTypeMap = new HashMap<>();
            Long salaryCategoryId = Long.valueOf(staffValues.getString("salaryCategory_id"));
            // 获取工资计算公式
            JSONObject salaryCategory = salaryCategoryMap.get(salaryCategoryId);
            if (salaryCategory != null) {
                JSONObject expression = salaryCategory.getJSONObject("values").getJSONObject("expression");
                if (expression != null) {
                    expression.forEach((categoryName, expressionValue) ->  {
                        log.info("计算{}, 公式为：{}", categoryName, expressionValue);
                        if (StrUtil.isNotBlank(String.valueOf(expressionValue))) {
                            // 将公式替换为可以获取数据的新公式 "reduce(seq.vals(filter(firstLevelSalary, lambda(item) -> string.startsWith(item.key, 'teamId#') end)),  +, 0)"
                            String newExpressionValue = String.valueOf(expressionValue);
                            newExpressionValue = newExpressionValue.replace("teamId", teamId);
                            newExpressionValue = newExpressionValue.replace("staffId", String.valueOf(staffId));
                            newExpressionValue = newExpressionValue.replaceAll("staffCode", staffCode);
                            newExpressionValue = newExpressionValue.replace("salaryCategoryId", String.valueOf("'" + salaryCategoryId +"'"));
                            log.info("{} newExpressionValue: {}", categoryName, newExpressionValue);
                            Object result = AviatorEvaluator.execute(newExpressionValue, calculateParamMap);
                            BigDecimal b = new BigDecimal(String.valueOf(result));
                            result = b.setScale(2, RoundingMode.HALF_UP);
                            log.info("result = {}", result);
                            salaryTypeMap.put(categoryName, result);
                        }
                    });
                    String key = StrUtil.join("#", teamId, staffId);
                    salaryMap.put(key, salaryTypeMap);
                }
            } else {
                log.info("公式不存在，无法计算工资， 工号：{}", staffValues.get("code"));
            }
        }
        calculateParamMap.put("allSalary", salaryMap);
        return salaryMap;
    }




    /**
     * 计算第二层员工的薪资，并将计算结果存放到后续计算需要的参数{@code calculateParamMap}中
     * @param salaryCategoryMap
     * @param calculateParamMap
     * @param staffList
     * @return
     */
    private Map<String, Map<String, Object>> calculateSecondLevelSalary(Map<Long, JSONObject> salaryCategoryMap, Map<String, Object> calculateParamMap, List<JSONObject> staffList) {
        // key = teamId#userId
        Map<String, Map<String, Object>> salaryMap = new HashMap<>();
        for (int i = 0; i < staffList.size(); i++) {
            Long staffId = staffList.get(i).getLong("id");
            JSONObject staffValues = staffList.get(i).getJSONObject("values");
            String teamId = staffValues.getString("team_id");
            String staffCode = staffValues.getString("code");
            // 存储一个班组下的员工
            String key = StrUtil.join("#", teamId, staffId);
            HashMap<String, Object>  salaryTypeMap = new HashMap<>();
            salaryMap.put(key, salaryTypeMap);
            Long salaryCategoryId = Long.valueOf(staffValues.getString("salaryCategory_id"));
            // 获取工资计算公式
            JSONObject salaryCategory = salaryCategoryMap.get(salaryCategoryId);
            if (salaryCategory != null) {
                String salaryCategoryName = salaryCategory.getJSONObject("values").getString("name");
                JSONObject expression = salaryCategory.getJSONObject("values").getJSONObject("expression");
                if (expression != null) {
                    expression.forEach((categoryName, expressionValue) ->  {
                        log.info("{} 计算{}, 公式为：{}", salaryCategoryName, categoryName, expressionValue);
                        if (StrUtil.isNotBlank(String.valueOf(expressionValue))) {
                            // 将公式替换为可以获取数据的新公式 "reduce(seq.vals(filter(firstLevelSalary, lambda(item) -> string.startsWith(item.key, 'teamId#') end)),  +, 0)"
                            String newExpressionValue = String.valueOf(expressionValue);
                            newExpressionValue = newExpressionValue.replace("teamId", teamId);
                            newExpressionValue = newExpressionValue.replace("staffId", String.valueOf(staffId));
                            newExpressionValue = newExpressionValue.replaceAll("staffCode", staffCode);
                            newExpressionValue = newExpressionValue.replace("salaryCategoryId", String.valueOf("'" + salaryCategoryId +"'"));
                            log.info("{} 计算{} newExpressionValue: {}", salaryCategoryName, categoryName, newExpressionValue);
                            Object result = BigDecimal.ZERO;
                            if (StrUtil.isNotBlank(newExpressionValue)) {
                                result = AviatorEvaluator.execute(newExpressionValue, calculateParamMap);
                                if (result != null) {
                                    BigDecimal b = new BigDecimal(String.valueOf(result));
                                    result = b.setScale(9, RoundingMode.HALF_UP);
                                }
                            }
                            log.info("result = {}", result);
                            salaryTypeMap.put(categoryName, result);
                        }
                    });
                }
            } else {
                log.info("公式不存在，无法计算工资， 工号：{}", staffValues.get("code"));
            }
        }
        calculateParamMap.put("secondLevelSalary", salaryMap);
        return salaryMap;
    }

    /**
     * 计算最基层员工的薪资，并将计算结果存放到后续计算需要的参数{@code calculateParamMap}中
     * @param salaryCategoryMap
     * @param calculateParamMap
     * @param firstLevelStaffList
     * @return
     */
    private Map<String, Map<String, Object>> calculateFirstLevelSalary(Map<Long, JSONObject> salaryCategoryMap, Map<String, Object> calculateParamMap, List<JSONObject> firstLevelStaffList) {
        // key = teamId#userId
        Map<String, Map<String, Object>> salaryMap = new HashMap<>();
        for (int i = 0; i < firstLevelStaffList.size(); i++) {
            Long staffId = firstLevelStaffList.get(i).getLong("id");
            JSONObject staffValues = firstLevelStaffList.get(i).getJSONObject("values");
            String teamId = staffValues.getString("team_id");
            String staffCode = staffValues.getString("code");
            // 存储一个班组下的员工
            String key = StrUtil.join("#", teamId, staffId);
            HashMap<String, Object>  salaryTypeMap = new HashMap<>();
            salaryMap.put(key, salaryTypeMap);
            if (StrUtil.isBlank(staffValues.getString("salaryCategory_id"))) {
                continue;
            }
            Long salaryCategoryId = Long.valueOf(staffValues.getString("salaryCategory_id"));
            // 获取工资计算公式
            JSONObject salaryCategory = salaryCategoryMap.get(salaryCategoryId);
            if (salaryCategory != null) {
                String salaryCategoryName = salaryCategory.getJSONObject("values").getString("name");
                JSONObject expression = salaryCategory.getJSONObject("values").getJSONObject("expression");
                if (expression != null) {
                    expression.forEach((categoryName, expressionValue) ->  {
                        log.info("{} 计算{}, 公式为：{}", salaryCategoryName, categoryName, expressionValue);
                        // 将公式替换为可以获取数据的新公式 workReport.staffId#lineBodyId * workReportDetailPrice.staffId#lineBodyId
                        // 将公式替换为可以执行的新公式 atwisdomMapFunction.multiplyAndSumByKeyStart(workReport, workReportDetailPrice, 'staffId#lineBodyId', '*', '+')
                        if (StrUtil.isNotBlank(String.valueOf(expressionValue))) {
                            String newExpressionValue = String.valueOf(expressionValue);
                            newExpressionValue = newExpressionValue.replaceAll("staffId", String.valueOf(staffId));
                            newExpressionValue = newExpressionValue.replaceAll("teamId", String.valueOf(teamId));
                            newExpressionValue = newExpressionValue.replaceAll("staffCode", staffCode);
                            newExpressionValue = newExpressionValue.replace("salaryCategoryId", String.valueOf("'" + salaryCategoryId + "'"));
                            log.info("{} 计算{} newExpressionValue: {}", salaryCategoryName, categoryName, newExpressionValue);
                            Object result = BigDecimal.ZERO;
                            if (StrUtil.isNotBlank(newExpressionValue)) {
                                result = AviatorEvaluator.execute(newExpressionValue, calculateParamMap);
                                if (result != null) {
                                    BigDecimal b = new BigDecimal(String.valueOf(result));
                                    result = b.setScale(2, RoundingMode.HALF_UP);
                                }
                            }
                            log.info("result = {}", result);
                            salaryTypeMap.put(categoryName, result);
                        }
                    });
                }
            } else {
                log.info("公式不存在，无法计算工资， 工号：{}", staffValues.get("code"));
            }
        }
        calculateParamMap.put("firstLevelSalary", salaryMap);
        return salaryMap;
    }

    /**
     * 查询考勤记录
     * @return
     */
    private Map<String, JSONObject> queryWorkAttendance(String yearMonth) {
        String className = "workAttendance";
        String condition = "yearMonth = '" + yearMonth + "'";
        List<JSONObject> list = resourceInstanceDslService.query(condition, className, null);
        Map<String, JSONObject> resultMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(list)) {
            resultMap = list.stream().collect(Collectors.toMap(d->d.getJSONObject("values").getString("person_code"), d->d.getJSONObject("values")));
        }
        return resultMap;
    }


    /**
     *  查询所有工资计算指标，用于替换成真正需要计算的值
     * @return
     */
    private Map<String, String> querySalaryIndex() {
        String className = "salaryIndex";
        List<JSONObject> list = resourceInstanceDslService.query("", className, null);
        Map<String, String> resultMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(list)) {
            resultMap = list.stream().collect(Collectors.toMap(d->d.getJSONObject("values").getString("code"),
                    d->d.getJSONObject("values").getString("content")));
        }
        return resultMap;
    }

    /**
     * 查询系统标准工时
     */
    private Integer querySystemStandardManHour() {
        List<JSONObject> list = staticLogicInstanceDslService.query("", "SysConfig", "workHours,desc");
        JSONObject max = list.stream().max(Comparator.comparingInt(d -> d.getJSONObject("values").getInteger("workHours"))).get();
        Integer systemStandardManHour = max.getJSONObject("values").getInteger("workHours");
        return systemStandardManHour;
    }

    /**
     * 查询所有班组信息
     */
    private Map<String, JSONObject> queryAllTeam() {
        List<HierInstance> list = hierInstanceDslService.query("staticLogic", "team", "", "");
        Map<String, JSONObject> teamMap = list.stream().collect(Collectors.toMap(d -> d.getNodeId(), d -> d.getValues()));
        return teamMap;
    }

    /**
     * 查询所有部门信息
     */
    private Map<String, JSONObject> queryAllDept() {
        List<HierInstance> deptList = hierInstanceDslService.query("staticLogic", "dept", "", "");
        Map<String, JSONObject> dataMap = deptList.stream().collect(Collectors.toMap(d -> d.getNodeId(), d -> d.getValues()));
        return dataMap;
    }



    /**
     * 查询员工标准工时， 该职位应该出勤的时长
     * staticLogic / staticLogic / SysConfig
     */
    private Map<String, Double> queryStandardManHour(Map<Long, JSONObject> salaryCategoryMap) {
        List<JSONObject> list = staticLogicInstanceDslService.query("", "SysConfig", "workHours,desc");
        Integer standardManHour = list.get(0).getJSONObject("values").getInteger("workHours");
        Map<String, Double> resultMap = new HashMap();
        for (Map.Entry<Long, JSONObject> entry : salaryCategoryMap.entrySet()) {
            Long salaryCategoryId = entry.getKey();
            JSONObject salaryCategory = entry.getValue();
            Double workAttendanceDays = salaryCategory.getJSONObject("values").getDouble("workAttendanceDays");
            // 默认考勤天数为26天
            workAttendanceDays = workAttendanceDays == null ? 26 : workAttendanceDays;
            resultMap.put(String.valueOf(salaryCategoryId), standardManHour * workAttendanceDays);
        }
        return resultMap;
    }


    /**
     * 查询所有薪资配置
     * @return
     */
    private Map<Long, JSONObject> queryAllSalaryCategory() {
        // 查询所有工资计算指标，用于替换成真正需要计算的值
        Map<String, String> salaryIndexMap = querySalaryIndex();

        String className = "salaryCategory";
        List<JSONObject> salaryCategoryList = resourceInstanceDslService.query("", className, null);
        Map<Long, JSONObject> salaryCategoryMap = salaryCategoryList.stream().collect(Collectors.toMap(d -> d.getLong("id"), d -> d));
        salaryCategoryMap.forEach((k, salaryCategory) -> {
            JSONObject expression = salaryCategory.getJSONObject("values").getJSONObject("expression");
            if (expression != null) {
                expression.forEach((categoryName, expressionValue) ->  {
                    log.info("计算{}, 公式为：{}", categoryName, expressionValue);
                    if (StrUtil.isNotBlank(String.valueOf(expressionValue))) {
                        // 将公式替换为可以获取数据的新公式 "reduce(seq.vals(filter(firstLevelSalary, lambda(item) -> string.startsWith(item.key, 'teamId#') end)),  +, 0)"
                        String newExpressionValue = String.valueOf(expressionValue);
                        newExpressionValue = ExpressionUtil.replaceInnerBrace(newExpressionValue, salaryIndexMap);
                        expression.put(categoryName, newExpressionValue);
                    }
                });
            }
        });
        return salaryCategoryMap;
    }

    /**
     *  查询所有的物料工序价表， MaterialProcessPrice， 计算出一件物料对应的价钱，
     *  如：b-001报工一次，需要点焊四次，那么价全就是四次的总价，也就是一次报工的价钱
     * @return "#", materialBcode, lineBody  : price
     */
    private Map<String, String> queryAllMaterialProcessPrice() {
        Map<String, String> resultMap = new HashMap<>();
        String className = "MaterialProcessPrice";
        List<JSONObject> materialProcessPriceList = logicInstanceDslService.queryJsonByClassName(className);
        materialProcessPriceList.forEach(materialProcessPrice -> {
            JSONObject values = materialProcessPrice.getJSONObject("values");
            String materialBcode = values.getString("material_bcode");
            Integer lineBody = values.getInteger("lineBody");
            BigDecimal price = values.getBigDecimal("price");
            Integer quantity = values.getInteger("quantity");
            quantity = quantity == null ? 1 : quantity;
            String key = StrUtil.join("#", lineBody, materialBcode);
            resultMap.put(key,  "(" +quantity + "*" + price + ")");
        });
        return resultMap;
    }

    /**
     * 查询派工完结单
     * workType  1 计件，  2 计时
     * @param beginTime
     * @param endTime
     * @return  person_code : actualDuration
     */
    private Map<String, Double> queryDispatchComplete(String beginTime, String endTime) {
        Map<String, Double> resultMap = new HashMap<>();
        String className = "dispatchComplete";
        String condition = "isApproved = 1 and endTime >= '" + beginTime + "' and endTime <= '" + endTime + "'";
        List<JSONObject> dispatchCompleteList = resourceInstanceDslService.query(condition, className, null);
        dispatchCompleteList.forEach(d -> {
            // "person_code"
            String staffCode = d.getJSONObject("values").getString("person_code");
            Double actualDuration = d.getJSONObject("values").getDouble("actualDuration");
            String workType = d.getJSONObject("values").getString("workType");
            String key = staffCode + "#" + workType;
            resultMap.merge(key, actualDuration, Double::sum);
        });
        return resultMap;
    }


    /**
     * 查询派工完结单
     * @param beginTime
     * @param endTime
     * @return  "#", operator, lineBody,materialBcode : quantity
     */
    private Map<String, Integer> queryWorkReport(String beginTime, String endTime) {
        Map<String, Integer> resultMap =
                new HashMap<>();
        String className = "workReport";
        // 报工明细parentId
        String condition = "parentId = '4ja1eoa9f6o000' and workReportEndTime >= '" + beginTime + "' and  workReportEndTime <= '" + endTime + "' ";
        List<JSONObject> staffList = queryAllStaff();
        // todo: 测试用，上线前要删除
        // condition += " and id = 8753 ";
        List<HierInstance> workReportDetailList = hierInstanceDslService.query("logic", className, condition);
        if (CollectionUtil.isNotEmpty(workReportDetailList)) {
            workReportDetailList.forEach(d->{
                JSONObject values = d.getValues();
                // 报工人变成了多个
                JSONArray operatorArray = values.getJSONArray("operator");
                // 报工人对应多个报工班组
                JSONArray teamIdArray = values.getJSONArray("teamId");
                if (CollectionUtil.isEmpty(teamIdArray)) {
                    throwException("报工单中没有班组信息");
                }
                for (int i = 0; i < operatorArray.size(); i++) {
                    String staffId = String.valueOf(operatorArray.get(i));
                    String teamId = String.valueOf(teamIdArray.get(i));
                    Integer lineBody = values.getInteger("lineBody");
                    String materialBcode = values.getString("material_bcode");
                    Integer quantity = values.getInteger("workReportNumber");
                    String key = StrUtil.join("#", teamId, staffId, lineBody, materialBcode);
                    resultMap.merge(key, quantity, Integer::sum);
                }
            });
        }

        return resultMap;
    }

}
